package sketch.specs;

import java.util.LinkedHashMap;
import java.util.List;
import java.util.Map;

import org.eclipse.jdt.core.dom.CompilationUnit;
import org.eclipse.jdt.core.dom.MethodInvocation;
import org.eclipse.jdt.core.dom.SimpleName;

import sketch.ast.ASTFormatter;
import sketch.ast.ASTUtils;
import sketch.examples.TreeMap;
import sketch.util.Checker;
import junit.framework.Test;
import junit.framework.TestCase;
import junit.framework.TestSuite;

public class RandomObjectGenerationTest extends TestCase {
	
	public static Test suite() {
		return new TestSuite(RandomObjectGenerationTest.class);
	}
	
	public void testTreemapRandom() {
		String filePath = "./testfiles/sketch/specs/TreeMapRandom.java";
		CompilationUnit unit = ASTUtils.astRoot(filePath);
		RandomValueVisitor visitor = new RandomValueVisitor();
		unit.accept(visitor);
		//System.out.println(unit.toString());
		//assertTrue(visitor.getNumOfReplace() == 7);
		Map<MethodInvocation, SimpleName> values = visitor.getRandomValues();
		assertEquals(1, values.size());
		
		for(MethodInvocation m : values.keySet()) {
			System.out.println("key: " + m + ",  value: " + values.get(m));
		}
	}
	
	public void testRandomSequenceGen() {
		RandomSequenceCreator sequenceCreator = new RandomSequenceCreator(TreeMap.class);
		String seqTxt = sequenceCreator.getSequenceTxt("treemap");
		System.out.println(seqTxt);
	}
	
	public void testFindingClasses() {
		String filePath = "./testfiles/sketch/specs/TreeMapRandom.java";
		CompilationUnit unit = ASTUtils.astRoot(filePath);
		RandomValueVisitor visitor = new RandomValueVisitor();
		unit.accept(visitor);
		//System.out.println(unit.toString());
		//assertTrue(visitor.getNumOfReplace() == 7);
		Map<MethodInvocation, SimpleName> values = visitor.getRandomValues();
		assertEquals(1, values.size());
		
		for(MethodInvocation methodInvoke : values.keySet()) {
			String simpleName = values.get(methodInvoke).getIdentifier();
			List<Class<?>> clazz = RandomValueVisitor.getClasses(methodInvoke);
			for(Class<?> c : clazz) {
				System.out.println(c);
			}
		}
	}
	
	//it is a generated test
	public void testRemove() {
		TreeMap treemap = new TreeMap();
		treemap.put(1);
		treemap.put(2);
		sketch.examples.TreeMap var0 = new sketch.examples.TreeMap();
		java.lang.Integer var1 = new java.lang.Integer(0);
		java.lang.String var2 = var0.concreteString(0);
		java.lang.Integer var3 = new java.lang.Integer(1);
		java.lang.Integer var4 = new java.lang.Integer(1);
		java.lang.Integer var5 = new java.lang.Integer(100);
		var0.putThree(1, 1, 100);
		java.lang.Integer var7 = new java.lang.Integer(10);
		java.lang.Integer var8 = new java.lang.Integer(100);
		java.lang.Integer var9 = new java.lang.Integer(1);
		var0.putThree(10, 100, 1);
		java.lang.Integer var11 = new java.lang.Integer(1);
		boolean var12 = var0.containsKey(1);
		java.lang.Integer var13 = new java.lang.Integer(10);
		java.lang.Integer var14 = new java.lang.Integer(10);
		var0.putTwo(10, 10);
		var0.print();
		java.lang.Integer var17 = new java.lang.Integer(3);
		java.lang.Integer var18 = new java.lang.Integer(1);
		java.lang.Integer var19 = new java.lang.Integer(0);
		var0.putThree(3, 1, 0);
		java.lang.Integer var21 = new java.lang.Integer(100);
		var0.remove(100);
		var0.print();
		java.lang.String var24 = var0.toString();
		java.lang.Integer var25 = new java.lang.Integer(5);
		var0.remove(5);
		treemap = var0;
		treemap.remove(3);
	}
	
	public void testOutputTest() {
		String filePath = "./testfiles/sketch/specs/TreeMapRandom.java";
		CompilationUnit unit = ASTUtils.astRoot(filePath);
		RandomValueVisitor visitor = new RandomValueVisitor();
		unit.accept(visitor);
		//System.out.println(unit.toString());
		//assertTrue(visitor.getNumOfReplace() == 7);
		Map<MethodInvocation, SimpleName> values = visitor.getRandomValues();
		assertEquals(1, values.size());
		
		Map<MethodInvocation, String> randomSequences = new LinkedHashMap<MethodInvocation, String>();
		
		for(MethodInvocation methodInvoke : values.keySet()) {
			String simpleName = values.get(methodInvoke).getIdentifier();
			List<Class<?>> clazz = RandomValueVisitor.getClasses(methodInvoke);
			Checker.checkTrue(!clazz.isEmpty(), "The clazz list should not be empty, for invocation: " + methodInvoke);
			Class<?> mainClass = clazz.get(0);
			Class<?>[] others = (Class<?>[])clazz.subList(1, clazz.size()).toArray(new Class<?>[0]);
			RandomSequenceCreator sequenceCreator = new RandomSequenceCreator(mainClass, others);
			String seqTxt = sequenceCreator.getSequenceTxt(simpleName);
			//System.out.println(seqTxt);
			
			randomSequences.put(methodInvoke, seqTxt);
		}
		
		System.out.println("replacing...");
		
		RandomSequenceReplaceVisitor replaceVisitor = new RandomSequenceReplaceVisitor(values, randomSequences);
		unit.accept(replaceVisitor);
		
		System.out.println("Let's see the results.");
		
		System.out.println(ASTFormatter.formatUnit(replaceVisitor.getResult()));
	}
	
	public void testOutputTestsInOneSecond() {
		String filePath = "./testfiles/sketch/specs/TreeMapRandom.java";
		CompilationUnit unit = ASTUtils.astRoot(filePath);
		RandomValueVisitor visitor = new RandomValueVisitor();
		unit.accept(visitor);
		
		Map<MethodInvocation, SimpleName> values = visitor.getRandomValues();
		assertEquals(1, values.size());
		
		Map<MethodInvocation, List<String>> randomSequences = new LinkedHashMap<MethodInvocation, List<String>>();
		
		for(MethodInvocation methodInvoke : values.keySet()) {
			String simpleName = values.get(methodInvoke).getIdentifier();
			List<Class<?>> clazz = RandomValueVisitor.getClasses(methodInvoke);
			Checker.checkTrue(!clazz.isEmpty(), "The clazz list should not be empty, for invocation: " + methodInvoke);
			Class<?> mainClass = clazz.get(0);
			Class<?>[] others = (Class<?>[])clazz.subList(1, clazz.size()).toArray(new Class<?>[0]);
			RandomSequenceCreator sequenceCreator = new RandomSequenceCreator(mainClass, others);
			List<String> seq_txts = sequenceCreator.getSequenceTxtList(simpleName, 1); //1 second
			//System.out.println(seqTxt);
			randomSequences.put(methodInvoke, seq_txts);
		}
		
		Checker.checkTrue(randomSequences.size() == 1, "Assume the size is 1 now.");
		MethodInvocation invoke = null;
		for(MethodInvocation tmp : randomSequences.keySet()) {
			invoke = tmp;
		}
		Checker.checkNull(invoke, "Should not be null.");
		
		int count = 0;
		for(String seq_txt : randomSequences.get(invoke)) {
		  Map<MethodInvocation, String> replace_sequence = new LinkedHashMap<MethodInvocation, String>();
		  replace_sequence.put(invoke, seq_txt);
		  RandomSequenceReplaceVisitor replaceVisitor = new RandomSequenceReplaceVisitor(values, replace_sequence);
		  //CompilationUnit replace_unit = ASTUtils.deepClone(unit);
		  unit.accept(replaceVisitor);
		  
		  System.out.println("Let's see the results: " + (count++));
		  System.out.println(ASTFormatter.formatUnit(replaceVisitor.getResult()));
		}
		
	}
}